/**
 * 
 */
package stub;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import business.Servidor;

/**
 * @author kristian
 *
 */
public class StubRMI implements StubInterface {
	private static StubRMI instance = new StubRMI();
	
	private Tabla tabla;
	
	
	private StubRMI(){
		
	}
	
	public static StubInterface getInstance(){
		return instance;
	}
	

	/* (non-Javadoc)
	 * @see stub.StubInterface#rfsClose(int, java.lang.String)
	 */
	@Override
	public void rfsClose(int fd, String filename) throws ConnectionException,
			FileFoundException, IllegalAccessException, FileNotFoundException,
			IOException, RemoteException {
		
		// si el filedescriptor coincide con el nombre de archivo
		if (checkFile(fd, filename)) {
			// elimino el archivo de la tabla
            tabla.remove(fd);
        }

	}

	/* (non-Javadoc)
	 * @see stub.StubInterface#rfsOpen(java.lang.String, boolean)
	 */
	@Override
	public int rfsOpen(String filename, boolean modo)
			throws ConnectionException, FileFoundException,
			IllegalAccessException, FileNotFoundException, IOException,
			RemoteException {
		int fd = 0;
		File archivo;
		Servidor servidor = new Servidor();
		
		// chequea si el archivo puede ser abierto
		archivo = servidor.open(filename, modo);
		
		// si asi es
			// guarda la informacion asociada
            OpenFile fila = new OpenFile(archivo, archivo.getName());
            // en una tabla
            fd = tabla.add(fila);

		
		return fd;
	}

	/* (non-Javadoc)
	 * @see stub.StubInterface#rfsRead(int, java.lang.String)
	 */
	@Override
	public IData rfsRead(int fd, String filename) throws ConnectionException,
			FileFoundException, IllegalAccessException, FileNotFoundException,
			IOException, RemoteException {
		
		Servidor servidor = new Servidor();
		
		// chequea la consistencia de la informacion suministrada
		if (checkFile(fd, filename)) {
			// recupera la informacion asociada del archivo en base al file descriptor 
            OpenFile fila = tabla.get(fd);
            
            // se ubica en la posicion correcta
            long aux = fila.getSeek();
            
            byte[] data = new byte[Protocolo.TAMANIO_BLOQUE];
            //lee los datos
            fila = servidor.read(fila, data);
            
            // calcula la carga util
            aux = fila.getSeek() - aux;
            
            //TODO armar el data
            IData salida = new Data(aux,data);
            
            return salida;
        }
		
		return null;
	}

	/* (non-Javadoc)
	 * @see stub.StubInterface#rfsWrite(int, java.lang.String, byte[], int)
	 */
	@Override
	public void rfsWrite(int fd, String filename, byte[] stream, int longitud)
			throws ConnectionException, FileFoundException,
			IllegalAccessException, FileNotFoundException, IOException,
			RemoteException {
		
		if (checkFile(fd, filename)) {
            OpenFile fila = tabla.get(fd);
            Servidor servidor = new Servidor();

            servidor.write(fila, stream, longitud);
        }

	}
	
	private boolean checkFile(int fd, String nombreArchivo) {
        OpenFile fila = tabla.get(fd);
        if (fila != null) {
            return (fila.getNombreArchivo().compareTo(nombreArchivo) == 0);
        } else {
            return false;
        }
    }
	
	static public void main(String args[]) {
//		if (System.getSecurityManager() == null) {
//            System.setSecurityManager(new SecurityManager());
//        }
		
        try {
        	// obtiene el objeto remoto
            StubInterface api = StubRMI.getInstance();
            
            // exporta el objeto remoto y obtiene el stub del objeto remoto
            StubInterface stub = (StubInterface) UnicastRemoteObject.exportObject(api, 0);
            
            // recupera el registro
            Registry registry = LocateRegistry.getRegistry();
            
            // asocia el stub con el nombre
            registry.rebind(Protocolo.API_FS, stub);
            System.out.println("se creo el ambiente RMI");
        } catch (Exception e) {
            System.err.println("error, mostrando stack trace:");
            e.printStackTrace();
        }

	}

}
